<?php

namespace addons\mplogin\controller\traits;
use addons\mplogin\library\UserAuth;
use addons\mplogin\model\BindUser;
use addons\mplogin\model\Key;
use app\common\library\Token;
use think\Cache;
use think\Config;
use think\Cookie;
use think\Exception;
use think\Hook;
use think\Lang;
use think\Request;
use think\Session;
use think\Validate;
use fast\Random;
use think\Db;
use think\exception\PDOException;
trait User
{

    /*二维码KEY*/
    public function key()
    {
        $temp_key = Key::setKey("user");
        $url = addon_url("mplogin/user/verify", ['key' => $temp_key->key], true, true);
        return $this->emit(1, '', ['url' => $url, "key" => $temp_key->key]);
    }

    /*检查KEY状态*/
    public function ticket()
    {
        if ($this->request->isAjax()) {
            try {
                $key = $this->request->param("key");
                if ($key && $keyInfo = Key::getKey($key)) {
                    if ($keyInfo->state == 2) {
                        return $this->emit($keyInfo->state, $keyInfo->state_text, [
                            'ticket' => $keyInfo->login_token,
                            "url"    => addon_url("mplogin/user/login"),
                            "token"  => $token = Request::instance()->token("__token__", "md5")
                        ]);
                    }
                    return $this->emit($keyInfo->state, $keyInfo->state_text);
                }
            } catch (\Exception $e) {
                return $this->emit(0, $e->getMessage());
            }
        }
    }

    /*用户微信授权*/
    public function verify()
    {
        try {
            $key = $this->request->param("key");
            $this->assign("sure_url", addon_url("mplogin/user/sure", ["key" => $key]));
            $this->assign("bind_url", addon_url("mplogin/user/bind"));
            $this->assign("unbind_url", addon_url("mplogin/user/unbind"));
            $this->assign("reg_url", addon_url("mplogin/user/regLogin"));
            $config=$this->conf;
            if(isset($config['auto_reg']) && $config['auto_reg']==1){
                $this->assign("wechat_auto_reg",'1');
            }else{
                $this->assign("wechat_auto_reg",'0');
            }
            if (!$key || !Key::getKey($key)) {
                return $this->emit(0, "登陆授权失败");
            } else {
                $this->key = $key;
                $this->assign("key", $key);
                $this->wechat->setRedirect_uri(addon_url('mplogin/user/verify', ["key" => $this->key], true, true)); //微信登录回调
            }
            if (!$this->request->param("code")) {
                $this->wechat->getCode();
            } else {
                $key_info = Key::getKey($key);
                if ($key_info->state != 0) { //判断扫码状态
                    return $this->emit(0, "登陆授权失败");
                } else {
                    $key_info->state = 1;
                    $key_info->scan_time = time();
                    $key_info->scan_ip = $this->request->ip();
                }
                $user = $this->wechat->codeToUserInfo();
                $openid = $user['openid'];
                Session::set("openid", $openid);
                $key_info->scan_openid = $openid;
                $key_info->save();
                if ($key_info->cli !== $this->cli) {
                    return $this->emit(0, "验证失败");
                }
                if ($this->conf['subscribe'] == 1 && $user['subscribe'] === 0) {
                    $key_info->state = -3;
                    $key_info->save();
                    return $this->emit(-3, "请先关注公众号", $this->conf['image']);
                }
                $user = BindUser::getUser($openid);
                if ($user && $userInfo = $user->user) {
                    $token = md5($key_info->salt . $key_info->ip . $key_info->session_id . $this->cli); //设置登录凭证
                    Session::set("login_token", $token);
                    Session::set("login_username", $userInfo->username);
                    return $this->emit(3, $token, $userInfo->username);
                }
                $key_info->state = -2;
                $key_info->save();
                return $this->emit(-2, "您尚未绑定账号", '请先绑定后再扫码登陆');
            }
        } catch (\Exception $e) {
            return $this->emit(0, $this->conf['debug'] == 1 ? $e->getMessage() : "网络错误");
        }
    }

    /*自动注册*/
    public function regLogin()
    {
        try{
            $config=get_addon_config('mplogin');
            if($config['auto_reg']==1){
                $openid = Session::get("openid");
                if (!$openid) {
                    return $this->emit(0, "微信授权失败,请重新扫码");
                }
                Db::startTrans();
                //$auth_user=Session::get('auth_userInfo');  //获取授权微信信息
                $user=  $this->auto_reg();
                if (!$user || !BindUser::bind($openid, $user->id)) {
                    Db::rollback();
                    return $this->emit(0, "绑定失败,请重试");
                }
                Db::commit();
                $re= BindUser::getUser($openid);
                $auth=$re->user;
                hook("mplogin_bind_tpl", compact("openid", "auth"));
                return $this->emit(1, "注册成功,请重新扫码登录");
            }
        }catch (\Exception $e){
            return $this->emit(0, $e->getMessage());
        }
        exit;
    }

    protected function auto_reg($params=[])
    {
        // 先随机一个用户名,随后再变更为u+数字id
        $username = Random::alnum(20);
        $password = Random::alnum(6);
        $domain = request()->host();
        $auth = \app\common\library\Auth::instance();
        Db::startTrans();
        try {
            // 默认注册一个会员
            $result = $auth->register($username, $password, $username . '@' . $domain, '', [], 0);
            if (!$result) {
                return false;
            }
            $user = $auth->getUser();
            $fields = ['username' => 'u' . $user->id, 'email' => 'u' . $user->id . '@' . $domain];
            if(empty($params)){
                $openid = Session::get("openid");
                $wxInfo= $this->wechat->userInfo($openid);
                isset($wxInfo['nickname']) &&  $fields['nickname']=$wxInfo['nickname'];
                isset($wxInfo['headimgurl']) &&  $fields['avatar']=$wxInfo['headimgurl'];
            }else{
                isset($params['nickname']) && $fields['nickname'] = $params['nickname'];
                isset($params['avatar']) && $fields['avatar'] = $params['avatar'];
            }
            // 更新会员资料
            $user = \app\common\model\User::get($user->id);
            $user->save($fields);
            Db::commit();
            return $user;
        } catch (PDOException $e) {
            Db::rollback();
            $auth->logout();
            return false;
        }
    }



    /*用户确认登陆*/
    public function sure()
    {
        if ($this->request->isPost() && $key = $this->request->param("key")) {
            try {
                $key_info = Key::getKey($key);
                $token = Session::pull("login_token");
                $login_name = Session::pull("login_username");
                if ($key_info->state == 1 && $token) {
                    $key_info->login_token = $token;
                    $key_info->save();
                    Cache::set($token, $token, 10);
                    return $this->emit(5, "登录成功", $login_name);
                } else {
                    return $this->emit(0, "操作超时");
                }
            } catch (\Exception $e) {
                return $this->emit(0, $this->conf['debug'] == 1 ? $e->getMessage() : "登陆授权失败");
            }
        }
    }


    /*客户端登陆*/
    public function login()
    {
        Lang::load(APP_PATH . "index" . '/lang/zh-cn/user.php');
        if ($this->request->isPost()) {
            try {
                $ticket = $this->request->param("ticket");
                $info = Key::getToken($ticket);
                if (!$info) {
                    $this->error("登录信息不存在");
                }
                $cache_ticket = Cache::pull($ticket);
                if (!$cache_ticket || $info->state == -1) {
                    $this->error("登录超时",'');
                }
                if(!Validate::token('__token__','',['__token__'=>$this->request->param("__token__")])){
                    $this->error( "TOKEN验证失败",'');
                }
                if (!Key::checkToken($ticket)) {
                    $this->error(Key::keyError());
                }
                $info->state = -1;
                $info->save();  //更新token;
                $openid = $info->scan_openid;
                $bindInfo = BindUser::getUser($openid);
                $auth = UserAuth::instance();
                Hook::add('user_login_successed', function ($user) use ($auth) {
                    $expire = input('post.keeplogin') ? 30 * 86400 : 0;
                    Cookie::set('uid', $user->id, $expire);
                    Cookie::set('token', $auth->getToken(), $expire);
                });
                $login_status= $auth->direct($bindInfo->user_id);
                if($login_status){
                    if($auth->status != 'normal'){  //是否禁用
                        Token::delete($auth->getToken());
                        Cookie::delete('uid');
                        Cookie::delete('token');
                        exception('Account is locked');
                    }
                    $auth = $bindInfo->user;
                    hook('mplogin_success', $bindInfo);
                    hook('mplogin_login_tpl', compact("openid", "auth"));
                    $this->redirect(url("index/user/index",[],true));
                } else {
                    $msg = $auth->getError();
                    $msg = $msg ? __($msg) : __('登录失败,请重试');
                    $this->error($msg, "/index/user/index", ['token' => $this->request->token()]);
                }
            } catch (Exception $e) {
                $this->error(__($e->getMessage()), "/index/user/login");
            }
        }
    }

    /*绑定会员*/
    public function bind()
    {
        Lang::load(APP_PATH . "index" . '/lang/zh-cn/user.php');
        if ($this->request->isPost()) {
            try {
                $account = $this->request->post('username');
                $password = $this->request->post('password');
                $token = $this->request->post('__token__');
                $rule = [
                    'account'  => 'require|length:3,50',
                    'password' => 'require|length:6,30'
                ];
                $msg = [
                    'account.require'  => 'Account can not be empty',
                    'account.length'   => 'Account must be 3 to 50 characters',
                    'password.require' => 'Password can not be empty',
                    'password.length'  => 'Password must be 6 to 30 characters',
                ];
                $data = [
                    'account'   => $account,
                    'password'  => $password,
                    '__token__' => $token,
                ];
                $validate = new Validate($rule, $msg);
                $result = $validate->check($data);
                if (!$result) {
                    return $this->emit(0, __($validate->getError()),$this->request->token());
                }
                $openid = Session::get("openid");
                if (!$openid) {
                    return $this->emit(0, "微信授权失败,请重新扫码");
                }
                $auth = UserAuth::instance();
                if ($auth->login($account, $password)) {
                    $info=BindUser::getOpenid($auth->id);
                    if($info){
                        if($info->mp_openid==$openid){
                            return $this->emit(0, "你已经绑定了微信号",$this->request->token());
                        }else{
                            return $this->emit(0, "账号已绑定了其他微信号，请解绑后操作",$this->request->token());
                        }
                    }
                    if (!BindUser::bind($openid, $auth->id)) {
                        return $this->emit(0, "绑定失败,请重试",$this->request->token());
                    }
                    hook("mplogin_bind_tpl", compact("openid", "auth"));
                    return $this->emit(1, "绑定成功,请重新扫码登录");
                } else {
                    return $this->emit(0, $auth->getError(),$this->request->token());
                }
            } catch (\Exception $e) {
                return $this->emit(0, $e->getMessage(),$this->request->token());
            }
        }
    }
    /*解除绑定*/
    public function unbind()
    {
        if ($this->request->isPost()) {
            $openid = Session::get("openid");
            if (!$openid) {
                return $this->emit(0, "微信授权失败,请重新扫码");
            }
            $re= BindUser::getUser($openid);
            if (!$re) {
                return $this->emit(0, "未绑定账号");
            }
            $auth=$re->user;
            $re && $re->delete();
            hook('mplogin_unbind_tpl',compact("openid", "auth"));
            return $this->emit(1, "解绑成功");
        }
    }

}
